package com.t2two.example.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @version 1.0
 * @description: 行政区划地址转换工具类
 * @author: lifei
 * @date: 2024/7/22 16:35
 */
public class RegionAddressUtil {

    /**
     * 从地址串中解析提取出省市区乡镇村庄等信息（正则表达式可能无法囊括所有的输入）
     * @param address   地址信息
     * @return          解析后的地址Map
     */
    public static Map<String,String> addressResolution(String address){
        if(StringUtils.isBlank(address)){
            return null;
        }
        // 百度到的正则
//        String regex="(?<province>[^省]+自治区|.*?省|.*?行政区|.*?市)(?<city>[^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县)(?<county>[^县]+县|.+区|.+市|.+旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<village>.*)";
        // 修改后的正则
        String regex = "(?<province>[^省]+省|.+自治区|[^澳门]+澳门|[^香港]+香港|[^市]+市)?(?<city>[^自治州]+自治州|[^特别行政区]+特别行政区|[^市]+市|.*?地区|.*?行政单位|.+盟|市辖区|[^县]+县)(?<county>[^县]+县|[^市]+市|[^区]+区|[^乡]+乡|[^镇]+镇|[^村]+村|.+场|.+旗|.+海域|.+岛)?(?<town>[^乡]+乡|[^镇]+镇|[^村]+村|[^街道]+街道|[^社区]+社区|[^所]+所|[^办事处]+办事处|[^服务中心]+服务中心|[^开发区]+开发区|.+社|.+居委会)?(?<village>[^村]+村|[^组]+组|[^居委会]+居委会|[^村委会]+村委会|[^居民委员会]+居民委员会|[^社区]+社区|.+小区|.+园|.+区)?(?<address>.*)";

        //2、创建匹配规则
        Matcher m = Pattern.compile(regex).matcher(address);
        String province;
        String city;
        String county;
        String town;
        String village;
        String detailAddress;
        Map<String,String> map = new HashMap<>(16);

        while (m.find()){
            //加入省
            province = m.group("province");
            map.put("province", province == null ? "" : province.trim());
            //加入市
            city = m.group("city");
            map.put("city", city == null ? "" : city.trim());
            //加入区
            county = m.group("county");
            map.put("county", county == null ? "" : county.trim());
            // 加入乡镇
            town = m.group("town");
            map.put("town", town == null ? "" : town.trim());
            // 加入村庄
            village = m.group("village");
            map.put("village", village == null ? "" : village.trim());

            //详细地址
            detailAddress = m.group("address");
            map.put("address", detailAddress == null ? "" : detailAddress.trim());
        }
        return map;
    }



    /**
     *  根据行政区划编码获取前缀
     * @param regionalCode 行政区划编码
     * @return 前缀
     */
    public static String getPrefixRegionCodeByRegionalCode(String regionalCode){
        if(StringUtils.isBlank(regionalCode)){
            return null;
        }
        String substring1 = regionalCode.substring(2, 4);
        if("00".equals(substring1)){
            return regionalCode.substring(0,2);
        }
        String substring2 = regionalCode.substring(4, 6);
        if("00".equals(substring2)){
            return regionalCode.substring(0,4);
        }
        String substring3 = regionalCode.substring(6, 9);
        if("000".equals(substring3)){
            return regionalCode.substring(0,6);
        }
        String substring4 = regionalCode.substring(9, 12);
        if("000".equals(substring4)){
            return regionalCode.substring(0,9);
        }
        return regionalCode;
    }

    /**
     * 校验证件号码
     * @param idNumber 证件号码
     * @return 是否合法
     */
    public static boolean validateCertificateNumber(String idNumber) {
        if(StringUtils.isBlank(idNumber)){
            return false;
        }
        // 校验身份证号码格式
        String regex = "(^\\d{17}(\\d|X|x)$)";
        if (!idNumber.matches(regex)) {
            return false;
        }
        // 校验生日
        String birthday = idNumber.substring(6, 14);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        dateFormat.setLenient(false);
        try {
            dateFormat.parse(birthday);
        } catch (ParseException e) {
            return false;
        }
        // 校验校验码
        char[] chars = idNumber.toCharArray();
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += (chars[i] - '0') * Math.pow(2, 17 - i) % 11;
        }
        int checkCode = (12 - sum % 11) % 11;
        if (checkCode == 10 && (chars[17] == 'X' || chars[17] == 'x')) {
            return true;
        }
        if (checkCode == (chars[17] - '0')) {
            return true;
        }
        return false;
    }
}
